package com.yonyou.le.unattended.web.selfhand;

import java.io.IOException;
import java.util.Date;
import java.util.concurrent.TimeUnit;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.google.gson.Gson;
import com.yonyou.iuap.mvc.type.JsonResponse;
import com.yonyou.le.unattended.cache.DeviceCacheManager;
import com.yonyou.le.unattended.cache.MonitorCacheManager;
import com.yonyou.le.unattended.cache.MonitorCacheTypeEnum;
import com.yonyou.le.unattended.entity.meta.CarInfoData;
import com.yonyou.le.unattended.entity.meta.SelfhandStatusEnum;
import com.yonyou.le.unattended.exception.NoGateTargetAdaptorException;
import com.yonyou.le.unattended.exception.NoLEDTargetAdaptorException;
import com.yonyou.le.unattended.exception.NoTargetDeviceException;
import com.yonyou.le.unattended.service.LedService;
import com.yonyou.le.unattended.service.PollService;
import com.yonyou.le.unattended.service.WsMessageService;
import com.yonyou.le.unattended.util.CommonUtils;
import com.yonyou.le.unattended.util.FindDevice;
import com.yonyou.le.unattended.util.ProConstant;
import com.yonyou.le.unattended.web.BaseController;
import com.yonyou.le.unattended.websocket.PicStatus;
import com.yonyou.le.unattended.websocket.MonitorUtils;
import com.yonyou.le.unattended.websocket.MsgTypeEnum;
/**
 * 作业点服务for 发卡机
 * @author zhangbbd
 * 
 * /service/openDoor
 * /service/getWeight
 * /service/sendLed
 */
@RestController
@RequestMapping(value="/service")
public class SelfhandCardController extends BaseController {
	private Logger logger = LoggerFactory.getLogger(SelfhandCardController.class);
	
	@Autowired
	private PollService pollService;
	@Autowired
	private LedService ledService;
	@Autowired
	private WsMessageService wsMessageService;
	@Autowired
	private MonitorCacheManager monitorCacheManager;
	@Autowired
	private DeviceCacheManager deviceCacheManager;
	@Autowired
	private ProConstant constant;
	
	private final String OK="true";
	private final String ERROR="false";
	private final String NO_WEIGHT="0"; //地磅没有重量
	
	/**
	 * 判断磅上有没有车的阈值
	 */
	@Value("${op.weight_threshold}")
	private String weight_threshold;
//	/**
//	 * 抬杆等待时间1
//	 */
//	@Value("${op.wait_time1}")
//	private int wait_time1;
//	/**
//	 * 抬杆等待时间2
//	 */
//	@Value("${op.wait_time2}")
//	private int wait_time2;
//	/**
//	 * 抬杆等待时间3
//	 */
//	@Value("${op.wait_time3}")
//	private int wait_time3;
//	/**
//	 * 抬杆等待时间4
//	 */
//	@Value("${op.wait_time4}")
//	private int wait_time4;
	
	
	/**
     * 获取实时称重信息
     * 
     * @return
	 * @throws Exception 
     */
    @RequestMapping(value = "/getWeight", method = RequestMethod.POST)
    public Object getWeight(@RequestParam String carInfoData, HttpServletRequest request) throws Exception {    	
    	logger.debug("le getWeight args:"+carInfoData);
    	if(carInfoData!=null&&!"".equals(carInfoData)){
    		Gson gson = new Gson();
        	CarInfoData carInfo = gson.fromJson(carInfoData, CarInfoData.class);
        	logger.info("获取实时重量"+carInfo);
        	String opcode=carInfo.getOpcode();
        	if(StringUtils.isNoneBlank(opcode)){
        		//取重之前判断红外状态
				String redA = monitorCacheManager.getCacheData(MonitorCacheTypeEnum.INFRA_RED_A, opcode, String.class);
				String redB = monitorCacheManager.getCacheData(MonitorCacheTypeEnum.INFRA_RED_B, opcode, String.class);
				logger.info("le getWeight " + opcode + " redstatus:" + redA + "-" + redB);
				if(redA == null || redB == null){
					String message= "红外连接异常：请检查作业点下磅前红外与适配器的连接！";
					logger.error(message);
					JsonResponse buildSuccess = super.buildSuccess(message);
                	buildSuccess.setMessage(ERROR);
                	buildSuccess.setSuccess(OK);
            		return buildSuccess;
				}
				boolean status = BooleanUtils.toBoolean(redA) && BooleanUtils.toBoolean(redB);
				if(status){
					//取重
	        		String weight = monitorCacheManager.getCacheData(MonitorCacheTypeEnum.CURRENT_WEIGHT, opcode, String.class);
	        		if(weight!=null){
	        			JsonResponse buildSuccess = super.buildSuccess(weight);
	                	buildSuccess.setMessage(OK);
	                	buildSuccess.setSuccess(OK);
	            		return buildSuccess;
	        		}else{
	        			JsonResponse buildSuccess = super.buildSuccess(NO_WEIGHT);
	                	buildSuccess.setMessage(OK);
	                	buildSuccess.setSuccess(OK);
	            		return buildSuccess;
	        		}
					
				}else{
					logger.error("红外被挡，请排除错误，重新刷卡");
					JsonResponse buildSuccess = super.buildSuccess("红外被挡，请排除错误，重新刷卡");
                	buildSuccess.setMessage(ERROR);
                	buildSuccess.setSuccess(OK);
            		return buildSuccess;
				}
        		
        		
        	}else{
        		JsonResponse buildSuccess = super.buildSuccess("缺少作业点编号.");
            	buildSuccess.setMessage(ERROR);
            	buildSuccess.setSuccess(OK);
        		return buildSuccess;
        	}
        	
        	
    	}else{
    		JsonResponse buildSuccess = super.buildSuccess("msg", "参数 carInfo为空");
        	buildSuccess.setMessage(ERROR);
        	buildSuccess.setSuccess(OK);
    		return buildSuccess;
    	}
     }
    
    /**
     * 检查磅上有没有车
     * @param carInfoData
     * @param request
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/checkHasCar", method = RequestMethod.POST)
    public Object checkHasCar(@RequestParam String carInfoData, HttpServletRequest request) throws Exception {    	
    	logger.debug("le checkHasCar args:"+carInfoData);
    	if(carInfoData!=null&&!"".equals(carInfoData)){
    		Gson gson = new Gson();
        	CarInfoData carInfo = gson.fromJson(carInfoData, CarInfoData.class);
        	String opcode=carInfo.getOpcode();
        	if(StringUtils.isNoneBlank(opcode)){
        		//检查服务是否启动
        		boolean checkAdaptorOK = checkAdaptorOK(opcode);
        		if(!checkAdaptorOK){
        			JsonResponse buildSuccess = super.buildSuccess("当前位置适配器服务没有启动，请联系管理员！");
                	buildSuccess.setMessage(ERROR);//可以上磅
                	buildSuccess.setSuccess(OK);
            		return buildSuccess;
        		}
        		//判断磅磅上是否有车
        		boolean hasCar = hasCar(opcode);
        		if(hasCar){//有车
        			JsonResponse buildSuccess = super.buildSuccess("磅上有车，请稍后！");
                	buildSuccess.setMessage(ERROR);//不能上磅
                	buildSuccess.setSuccess(OK);
            		return buildSuccess;
        		}else{
        			JsonResponse buildSuccess = super.buildSuccess("磅上无车.");
                	buildSuccess.setMessage(OK);//可以上磅
                	buildSuccess.setSuccess(OK);
            		return buildSuccess;
        		}
        		
        	}else{
        		JsonResponse buildSuccess = super.buildSuccess("缺少作业点编号.");
            	buildSuccess.setMessage(ERROR);
            	buildSuccess.setSuccess(OK);
        		return buildSuccess;
        	}
    	}else{
    		JsonResponse buildSuccess = super.buildSuccess("msg", "参数 carInfo为空");
        	buildSuccess.setMessage(ERROR);
        	buildSuccess.setSuccess(OK);
    		return buildSuccess;
    	}
    }
    /**
     * 抬杆(共同接口，四个流程)，根据carInfoData的selfhandstatus来决定是哪一步。
     * @param request
     * @return
     */
	@RequestMapping(value = "/openDoor", method = RequestMethod.POST)
    public Object openDoor(@RequestParam String carInfoData, HttpServletRequest request) {
		logger.debug("le openDoor args:"+carInfoData);
		if(carInfoData!=null&&!"".equals(carInfoData)){
    		Gson gson = new Gson();
        	CarInfoData carInfo = gson.fromJson(carInfoData, CarInfoData.class);
        	//缓存
        	monitorCacheManager.updateCarInfo(carInfo.getOpcode(), carInfo);
        	String selfhandstatus = carInfo.getSelfhandstatus();
        	SelfhandStatusEnum status = SelfhandStatusEnum.getEnum(selfhandstatus);
         	if(status != null){
        		logger.info("流程："+status.getName());
        		switch(status){
            	case EnterOn:
            		return enterOn(carInfo);
            	case EnterOut:
            		return enterOut(carInfo);
            	case SecondOn:
            		return secondOn(carInfo);
            	case SecondOut:
            		return secondOut(carInfo);
            	default:
            			break;
            	}
        	}else{
        		logger.error("未知状态..");
        	}
        	
     	}
    	JsonResponse buildSuccess = super.buildSuccess("参数 carInfo为空！");
    	buildSuccess.setMessage(ERROR);
    	buildSuccess.setSuccess(OK);
		return buildSuccess;
 
    }
   
	
    
    /**
     * 一次计量进场
     * @param request
     * @return
     */
    private Object enterOn(CarInfoData carInfo) {     	
		String opcode=carInfo.getOpcode();
		
//		boolean hasCar = hasCar(opcode);
//		if(hasCar){
//			//通知磅上有车
//			sendLED_Before(carInfo.getOpcode(), "磅上有车，请稍后.."); 
//			JsonResponse buildSuccess = super.buildSuccess("磅上有车，请稍后..");
//        	buildSuccess.setMessage(ERROR);
//        	buildSuccess.setSuccess(OK);
//    		return buildSuccess;
//		}
	
        //通知监控车辆信息
		wsMessageService.sendCar(opcode, carInfo);
		//通知监控发卡成功
		wsMessageService.sendMsg(carInfo.getOpcode(),CommonUtils.buildDateMessage(carInfo.getCarno()+"发卡成功,上磅计量"));
		//修改和通知监控车辆状态
		monitorCacheManager.updatePictureStatus(opcode, 1);
		wsMessageService.changeState(carInfo.getOpcode(),PicStatus.STATUS_POLL_LEFT.getIndex());
		
		//通知LED发卡成功		
		sendLED_Before(carInfo.getOpcode(), carInfo.getCarno()+"发卡成功,请上磅计量"); 
    	
		//找到对应设备
    	String pos_type=FindDevice.getDaoZha_Before();    	
		try {
			TimeUnit.SECONDS.sleep(constant.wait_time1);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		logger.debug("发卡抬杆:"+carInfo.getCarno());
		boolean open = open(pos_type,opcode,carInfo);
		if(open){
			JsonResponse buildSuccess = super.buildSuccess(carInfo.getCarno()+"发卡成功，请上磅计量");
	    	buildSuccess.setMessage(OK);
	    	buildSuccess.setSuccess(OK);
			return buildSuccess;
		}else{
			JsonResponse buildSuccess = super.buildSuccess("抬杆失败，请联系管理员.");
	    	buildSuccess.setMessage(ERROR);
	    	buildSuccess.setSuccess(OK);
			return buildSuccess;
		}
    }
    
    
	
    /**
     * 保存榜单后，下磅，请求抬杆
     * 
     * @return
     */
    private Object enterOut(CarInfoData carInfo) {    	
    	String opcode = carInfo.getOpcode();//作业点编码

    	//通知监控车辆信息
		wsMessageService.sendCar(opcode, carInfo);
		//通知监控一次计量成功
		wsMessageService.sendMsg(carInfo.getOpcode(),CommonUtils.buildDateMessage(carInfo.getCarno()+"一次计量成功"));
    	//修改和通知监控车辆状态
		monitorCacheManager.updatePictureStatus(opcode, 3);
		wsMessageService.changeState(carInfo.getOpcode(),PicStatus.STATUS_POLL_RIGHT.getIndex());
		//通知LED一次计量成功
		sendLED_After(carInfo.getOpcode(), carInfo.getCarno()+"计量成功,请下磅");

    	//找到对应设备
    	String pos_type=FindDevice.getDaoZha_After();
    	try {
			TimeUnit.SECONDS.sleep(constant.wait_time2);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
    	logger.debug("一次计量抬杆:"+carInfo.getCarno());
    	boolean open = open(pos_type,opcode,carInfo);
    	
    	if(open){
    		JsonResponse buildSuccess = super.buildSuccess(carInfo.getCarno()+"一次计量成功");
        	buildSuccess.setMessage(OK);
        	buildSuccess.setSuccess(OK);
    		return buildSuccess;
    	}else{
			JsonResponse buildSuccess = super.buildSuccess("抬杆失败，请联系管理员.");
	    	buildSuccess.setMessage(ERROR);
	    	buildSuccess.setSuccess(OK);
			return buildSuccess;
		}
    	
    }
    /**
     * 二次计量，请求抬杆
     * 
     * @return
     */
    private Object secondOn(CarInfoData carInfo) {    	
    	String opcode=carInfo.getOpcode();
    	boolean hasCar = hasCar(opcode);
		if(hasCar){
			//通知磅上有车
			sendLED_After(carInfo.getOpcode(), "磅不为空，请等待"); 
			JsonResponse buildSuccess = super.buildSuccess("磅不为空，请等待");
        	buildSuccess.setMessage(ERROR);
        	buildSuccess.setSuccess(OK);
    		return buildSuccess;
		}
		
		
    	//通知监控车辆信息
		wsMessageService.sendCar(opcode, carInfo);
		//通知监控二次上磅抬杆
		wsMessageService.sendMsg(carInfo.getOpcode(),CommonUtils.buildDateMessage(carInfo.getCarno()+"读卡成功,请上磅计量"));
		//修改和通知监控车辆状态
		monitorCacheManager.updatePictureStatus(opcode, 1);
		wsMessageService.changeState(carInfo.getOpcode(),PicStatus.STATUS_POLL_LEFT.getIndex());
		
		//通知LED二次抬杆成功
		sendLED_After(carInfo.getOpcode(), carInfo.getCarno()+"读卡成功,请上磅计量");
    	
    	//找到对应设备
    	String pos_type=FindDevice.getDaoZha_After();//二次上磅抬杆  磅后
    	try {
			TimeUnit.SECONDS.sleep(constant.wait_time3);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
    	logger.debug("二次上磅抬杆:"+carInfo.getCarno());
    	boolean open = open(pos_type,opcode,carInfo);
    	if(open){
    		JsonResponse buildSuccess = super.buildSuccess(carInfo.getCarno()+"抬杆成功,请上磅计量.");
    		buildSuccess.setMessage(OK);
    		buildSuccess.setSuccess(OK);
    		return buildSuccess;
    	}else{
			JsonResponse buildSuccess = super.buildSuccess("抬杆失败，请联系管理员.");
	    	buildSuccess.setMessage(ERROR);
	    	buildSuccess.setSuccess(OK);
			return buildSuccess;
		}
    	
    }
    /**
     * 二次计量，下磅，请求抬杆
     * 
     * @return
     */
    private Object secondOut(CarInfoData carInfo){    	
	   	String opcode = carInfo.getOpcode();//作业点编码
    	
    	//通知监控车辆信息
		wsMessageService.sendCar(opcode, carInfo);
		//通知监控二次计量
		wsMessageService.sendMsg(carInfo.getOpcode(),CommonUtils.buildDateMessage(carInfo.getCarno()+"二次计量成功"));
		//修改和通知监控车辆状态
		monitorCacheManager.updatePictureStatus(opcode, 3);
		wsMessageService.changeState(carInfo.getOpcode(),PicStatus.STATUS_POLL_RIGHT.getIndex());
		
		//通知LED二次计量成功
		sendLED_Before(carInfo.getOpcode(), carInfo.getCarno()+"计量成功,请下磅");
    	
    	//找到位置，对应设备
    	String pos_type=FindDevice.getDaoZha_Before();
    	try {
			TimeUnit.SECONDS.sleep(constant.wait_time4);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
    	logger.debug("二次计量抬杆:"+carInfo.getCarno());
    	boolean open = open(pos_type,opcode,carInfo);
    	if(open){
    		JsonResponse buildSuccess = super.buildSuccess(carInfo.getCarno()+"计量成功,请下磅");
        	buildSuccess.setMessage(OK);
        	buildSuccess.setSuccess(OK);
    		return buildSuccess;
    	}else{
			JsonResponse buildSuccess = super.buildSuccess("抬杆失败，请联系管理员.");
	    	buildSuccess.setMessage(ERROR);
	    	buildSuccess.setSuccess(OK);
			return buildSuccess;
		}
    	


    }
       
    
    /**
     * 发送LED消息
     * @param carInfoData
     * @param request
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/sendLed", method = RequestMethod.POST)
    public Object sendLedMsg(@RequestParam String carInfoData,HttpServletRequest request) {    	
    	logger.info("sendLedMsg args:"+carInfoData);
    	if(carInfoData!=null&&!"".equals(carInfoData)){
    		Gson gson = new Gson();
        	CarInfoData carInfo = gson.fromJson(carInfoData, CarInfoData.class);
        	String opCode = carInfo.getOpcode();//作业点编码
        	
        	String selfhandstatus = carInfo.getSelfhandstatus();
			SelfhandStatusEnum status = SelfhandStatusEnum.getEnum(selfhandstatus);
			if(status != null){
				logger.info("流程："+status.getName());
				switch(status){
				case EnterOn:
					sendLED_Before(opCode, carInfo.getNotiMessage());
					break;
				case EnterOut:
					sendLED_After(opCode, carInfo.getNotiMessage());
					break;
				case SecondOn:
					sendLED_After(opCode, carInfo.getNotiMessage());
					break;
				case SecondOut:
					sendLED_Before(opCode, carInfo.getNotiMessage());
					break;
				default:
						break;
				}
			}else{
				logger.error("未知状态..");
			}
     		JsonResponse buildSuccess = super.buildSuccess();
    		buildSuccess.setSuccess(OK);
    		buildSuccess.setMessage(OK);
    		return buildSuccess;

    	}
    	JsonResponse buildSuccess = super.buildSuccess("参数carInfo为空");
    	buildSuccess.setMessage(ERROR);
    	buildSuccess.setSuccess(OK);
		return buildSuccess;
    }
    
    /**
     * 判断作业点下抬杆的服务适配器是否启动。
     * @param pos_type
     * @param opcode
     * @param carInfo
     * @return
     */
	private boolean checkAdaptorOK(String opcode){
		//抬杆
    	boolean result = false;
    	String deviceCode=deviceCacheManager.getMonitorDevice(opcode,FindDevice.getWeightPositionAndType(), String.class);
		try {
			result = pollService.checkOK(deviceCode);
		} catch (NoGateTargetAdaptorException e) {
			logger.error(e.getMessage());
			//通知监控
		} catch (NoTargetDeviceException e) {
			logger.error(e.getMessage());
			//e.printStackTrace();
			//通知监控
		}
		return result;
	}
    /**
     * 根据位置和作业点来抬杆
     * @param pos_type
     * @param opcode
     * @param carInfo
     * @return
     */
	private boolean open(String pos_type, String opcode, CarInfoData carInfo){
		//抬杆
    	boolean result = false;
    	String deviceCode=deviceCacheManager.getMonitorDevice(opcode,pos_type, String.class);
		try {
			result = pollService.pollUp(deviceCode);
		} catch (NoGateTargetAdaptorException e) {
			logger.error(e.getMessage());
			e.printStackTrace();
			//通知监控
    		wsMessageService.sendMsg(opcode,CommonUtils.formatDate(new Date())+e.getMessage());
		} catch (NoTargetDeviceException e) {
			logger.error(e.getMessage());
			//e.printStackTrace();
			//通知监控
    		wsMessageService.sendMsg(opcode,CommonUtils.formatDate(new Date())+e.getMessage());
		}
		if(!result){
    		wsMessageService.sendMsg(opcode,carInfo.getCarno()+"抬杆"+deviceCode+"失败，请求超时");
    	}
		return result;
	}
    
    /**
     * 发送到作业点下前LED
     * @param opCode
     * @param msg
     * @return
     * @throws NoLEDTargetAdaptorException 
     */
    private boolean sendLED_Before(String opCode,String msg){
    	//前置LED CODE
    	String deviceCode_before = deviceCacheManager.getMonitorDevice(opCode, FindDevice.getLED_Before(), String.class);
    	boolean result = true;
    	if(StringUtils.isNotBlank(deviceCode_before))
			try {
				result = ledService.showLed(deviceCode_before,msg);
			} catch (NoLEDTargetAdaptorException e) {
				logger.error(e.getMessage());
				wsMessageService.sendMsg(opCode,e.getMessage());
			} 
		else{
			logger.error("作业点："+opCode +"对应位置没有合适的LED");
    		result = false;
    	}
    	return result;
    	
     }
    /**
     * 发送到作业点下后LED
     * @param opCode
     * @param msg
     * @return
     * @throws NoLEDTargetAdaptorException 
     */
    private boolean sendLED_After(String opCode,String msg) {
    	//后置LED CODE
    	String deviceCode_after = deviceCacheManager.getMonitorDevice(opCode, FindDevice.getLED_After(), String.class);
    	boolean result = true;
    	if(StringUtils.isNotBlank(deviceCode_after))
			try {
				result = ledService.showLed(deviceCode_after,msg);
			} catch (NoLEDTargetAdaptorException e) {
				logger.error(e.getMessage());
				wsMessageService.sendMsg(opCode,e.getMessage());
			} 
		else{
    		logger.error("作业点："+opCode +"对应位置没有合适的LED");
    		result = false;
    	}
    	return result;
    	
     }
    
    /**
     * 判断磅上有没有车
     * @param opcode
     * @return
     */
    private boolean hasCar(String opcode){
    	//取重
		String weight = monitorCacheManager.getCacheData(MonitorCacheTypeEnum.CURRENT_WEIGHT, opcode, String.class);
		if(null == weight){
    		return false;
		}else{
			double w = Double.valueOf(weight);
    		if(w < constant.weight_threshold){
        		return false;
    		}else{
        		return true;
    		}
		}
    }
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    

    /**
     * 发送异常消息
     * @param carInfoData
     * @param request
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/sendExecMsg", method = RequestMethod.POST)
    public Object sendExecMsg(@RequestParam String carInfoData,HttpServletRequest request){    	
    	logger.info("sendExceptions args:"+carInfoData);
    	if(carInfoData!=null&&!"".equals(carInfoData)){
    		Gson gson = new Gson();
        	CarInfoData carInfo = gson.fromJson(carInfoData, CarInfoData.class);
        	String opCode = carInfo.getOpcode();//作业点编码
        	logger.info("sendExceptions");    	
        	try{
        		MonitorUtils.sendMessage(MsgTypeEnum.WS_TYPE_EXCEPTIONS.getName(), opCode, carInfo.getNotiMessage());
            	JsonResponse buildSuccess = super.buildSuccess("Success");
            	buildSuccess.setMessage(OK);
            	buildSuccess.setSuccess(OK);
        		return buildSuccess;
        	}catch(IOException e){
        		JsonResponse buildSuccess = super.buildSuccess("failing in sending message throught websocket!");
            	buildSuccess.setMessage(ERROR);
            	buildSuccess.setSuccess(OK);
        		return buildSuccess;
        	}
    	}
    	JsonResponse buildSuccess = super.buildSuccess("parameter carInfo is blank");
    	buildSuccess.setMessage(ERROR);
    	buildSuccess.setSuccess(OK);
		return buildSuccess;

    }
}